1 O que é Fine-Tuning?
Pegar um modelo que já sabe muito e ensiná-lo coisas específicas do seu domínio.
Pré-treinamento vs Fine-tuning
📚 Pré-treinamento
O que faz: Aprende padrões gerais de linguagem
Dados: Trilhões de tokens da internet
Custo: Milhões de dólares, semanas em GPUs
Ex: Llama 3 foi treinado em ~15T tokens.
🎯 Fine-tuning
O que faz: Adapta o modelo ao seu domínio
Dados: Milhares/milhões de exemplos específicos
Custo: Centenas de dólares, horas em GPU
Ex: Llama 3 fine-tuned para suporte Nimbus Cloud.
Quando usar Fine-tuning vs RAG?
| Situação | Recomendação | Por quê? |
|---|---|---|
| Conhecimento muda frequentemente | 🔍 RAG | RAG busca docs atualizados; FT precisa retreinar |
| Precisa citar fontes | 🔍 RAG | RAG rastreia origem; FT não |
| Tom/estilo específico da empresa | 🎯 Fine-tuning | Modelo internaliza o tom; RAG não controla estilo |
| Jargão técnico muito específico | 🎯 Fine-tuning | Modelo aprende vocabulário do domínio |
| Latência crítica | 🎯 Fine-tuning | Não precisa buscar chunks antes de responder |
| Base de conhecimento enorme | 🔍 RAG | FT tem limite de contexto; RAG busca sob demanda |
| Precisão máxima + contexto atualizado | 🔗 RAG + Fine-tuning | Melhor dos dois mundos |
2 LoRA e QLoRA — fine-tuning eficiente
Ajustar apenas 1% dos parâmetros em vez de 100% — 10x mais barato.
🎮 Simulador: LoRA em ação
Veja como LoRA ajusta apenas uma pequena fração dos parâmetros do modelo.
Ajuste o rank (r) e veja quantos parâmetros são treináveis
congelados
treináveis
Parâmetros treináveis: 8.000.000 (0.10%)
Memória necessária: ~16 GB
Interpretação: quadrados ciano = parâmetros que serão ajustados durante o treinamento. Quadrados escuros = pesos congelados. Quanto maior o rank (r), mais parâmetros treináveis, mas mais memória e tempo.
A matemática do LoRA
# Forward pass com LoRA # Em vez de: output = x @ W # W é a matriz de pesos original (ex: 4096 x 4096) # LoRA faz: output = x @ W + (x @ A) @ B * alpha # Onde: # W = matriz original (congelada, 4096 x 4096 = 16M parâmetros) # A = matriz de baixa dimensão (4096 x r, treinável) # B = matriz de baixa dimensão (r x 4096, treinável) # r = rank (tipicamente 8, 16, 32, 64) # alpha = fator de escala # Com r=16: # A: 4096 x 16 = 65.536 parâmetros # B: 16 x 4096 = 65.536 parâmetros # Total treinável por camada: 131.072 parâmetros # vs W original: 16.777.216 parâmetros # Redução: 128x menos parâmetros!
QLoRA — LoRA com quantização
| Método | Precisão | Memória (Llama 3 8B) | GPU necessária |
|---|---|---|---|
| Full Fine-tuning | FP16 | ~60 GB | A100 80GB |
| LoRA | FP16 | ~18 GB | RTX 4090 (24GB) |
| QLoRA | 4-bit | ~6 GB | RTX 3060 (12GB) |
3 Datasets de treinamento
A qualidade do seu dataset define a qualidade do modelo fine-tuned.
Formatos de dataset
Instrução + Resposta
Formato mais comum. Pares de (instrução, resposta ideal).
{
"instruction": "Classifique o ticket",
"input": "Timeout no /v2/sync",
"output": "prioridade_alta"
}
Conversacional (Chat)
Múltiplas turnos de conversa. Ideal para chatbots.
{
"messages": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
]
}
Completamento
Texto contínuo para completar. Bom para estilo/tom.
{
"prompt": "Prezado cliente,\n",
"completion": "informamos que seu ticket..."
}
🎮 Exemplo: Dataset para suporte Nimbus Cloud
Quantos exemplos você precisa?
| Objetivo | Exemplos | Qualidade esperada |
|---|---|---|
| Ajustar tom/estilo | 100-500 | Modelo internaliza o tom |
| Tarefa específica (classificação) | 500-2.000 | Alta precisão na tarefa |
| Domínio técnico completo | 5.000-50.000 | Modelo vira especialista |
| Comportamento complexo (raciocínio) | 10.000-100.000 | Modelo aprende padrões de raciocínio |
Boas práticas para datasets
Qualidade > quantidade
1.000 exemplos perfeitos valem mais que 10.000 medianos.
Diversidade
Cubra todos os tipos de perguntas que o modelo vai receber.
Limpeza
Remova duplicatas, exemplos contraditórios, dados sensíveis.
Balanceamento
Mesma quantidade de exemplos para cada classe/categoria.
4 Treinamento na prática
Código completo para fazer fine-tuning com QLoRA em Llama 3.
Setup do ambiente
# Instalar dependências pip install transformers peft datasets bitsandbytes accelerate pip install trl # Transformer Reinforcement Learning # Hardware recomendado: # - QLoRA 7B: GPU com 12GB+ (RTX 3060, RTX 4070) # - QLoRA 13B: GPU com 24GB+ (RTX 4090, A10) # - QLoRA 70B: GPU com 48GB+ (A6000, A100 40GB)
Código completo: QLoRA em Llama 3 8B
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training from trl import SFTTrainer, SFTConfig from datasets import load_dataset import torch # 1. Configuração de quantização (4-bit) bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type="nf4", # Normal Float 4-bit bnb_4bit_compute_dtype=torch.float16, bnb_4bit_use_double_quant=True # Quantização aninhada ) # 2. Carregar modelo base quantizado model_name = "meta-llama/Llama-3.1-8B" model = AutoModelForCausalLM.from_pretrained( model_name, quantization_config=bnb_config, device_map="auto" ) tokenizer = AutoTokenizer.from_pretrained(model_name) tokenizer.pad_token = tokenizer.eos_token # 3. Preparar modelo para treinamento k-bit model = prepare_model_for_kbit_training(model) # 4. Configuração LoRA lora_config = LoraConfig( r=16, # rank (quanto maior, mais capacidade, mais memória) lora_alpha=32, # fator de escala target_modules=["q_proj", "v_proj", "k_proj", "o_proj"], # módulos para aplicar LoRA lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) # 5. Aplicar LoRA ao modelo model = get_peft_model(model, lora_config) model.print_trainable_parameters() # trainable params: 8,388,608 || all params: 8,030,261,248 || trainable%: 0.1045 # 6. Carregar dataset dataset = load_dataset("json", data_files="nimbus_support_dataset.json") # 7. Configuração de treinamento training_args = SFTConfig( output_dir="./nimbus-support-llama3", num_train_epochs=3, per_device_train_batch_size=2, gradient_accumulation_steps=4, learning_rate=2e-4, # LR típico para LoRA fp16=True, logging_steps=10, save_strategy="epoch", optim="paged_adamw_8bit", # otimizador eficiente em memória max_seq_length=1024, warmup_ratio=0.03, lr_scheduler_type="cosine" ) # 8. Criar trainer trainer = SFTTrainer( model=model, train_dataset=dataset["train"], args=training_args, tokenizer=tokenizer ) # 9. Treinar! trainer.train() # 10. Salvar adapter model.save_pretrained("./nimbus-support-adapter") print("✅ Treinamento concluído! Adapter salvo.")
Usando o modelo fine-tuned
from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel # Carregar modelo base base_model = AutoModelForCausalLM.from_pretrained( "meta-llama/Llama-3.1-8B", load_in_4bit=True, device_map="auto" ) tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B") # Carregar adapter fine-tuned model = PeftModel.from_pretrained(base_model, "./nimbus-support-adapter") # Gerar resposta prompt = "Qual o timeout do endpoint /v2/sync?" inputs = tokenizer(prompt, return_tensors="pt").to("cuda") outputs = model.generate( **inputs, max_new_tokens=200, temperature=0.3, # baixa para precisão top_p=0.9 ) response = tokenizer.decode(outputs[0], skip_special_tokens=True) print(response) # "O timeout padrão do endpoint /v2/sync é 30 segundos..."
Hyperparâmetros importantes
| Parâmetro | Valor típico | O que faz |
|---|---|---|
| r (rank) | 8-64 | Tamanho dos adapters. Maior = mais capacidade, mais memória |
| lora_alpha | 16-64 | Fator de escala. Geralmente 2x o rank |
| learning_rate | 1e-4 a 3e-4 | Tamanho do passo de otimização |
| epochs | 2-5 | Quantas vezes o modelo vê o dataset |
| batch_size | 2-8 | Exemplos por passo. Depende da memória da GPU |
| max_seq_length | 512-2048 | Tamanho máximo do input+output |
5 Avaliação de modelos fine-tuned
Como saber se o fine-tuning funcionou — métricas e testes.
Métricas de avaliação
| Métrica | O que mede | Como calcular |
|---|---|---|
| Perplexity | Quão "surpreso" o modelo fica com o texto | Menor = melhor. Ideal: < 20 |
| BLEU / ROUGE | Similaridade com resposta de referência | 0-1. Maior = melhor |
| Exact Match | % de respostas idênticas ao esperado | Para classificação |
| Acurácia | % de previsões corretas | Para tarefas de classificação |
| Avaliação humana | Qualidade percebida por humanos | Nota 1-5 em uma amostra |
| LLM-as-Judge | Outro LLM avalia as respostas | GPT-4 avalia respostas do seu modelo |
🎮 Simulador: Comparando modelos
Veja como o modelo base se compara ao modelo fine-tuned em diferentes tarefas.
Performance em tarefas do domínio Nimbus Cloud
Interpretação: o modelo base acerta 45% das perguntas de suporte (não conhece o domínio). Fine-tuning sobe para 87%. RAG + Fine-tuning chega a 94% — o modelo entende o domínio E tem acesso a documentos atualizados.
Test set — separando dados
# Dividir dataset em treino e teste from sklearn.model_selection import train_test_split # 80% treino, 20% teste train_data, test_data = train_test_split( dataset, test_size=0.2, random_state=42 ) # Treina SÓ com train_data trainer = SFTTrainer( model=model, train_dataset=train_data, # ← apenas treino ... ) # Avalia com test_data (modelo NUNCA viu) def evaluate_model(model, test_data): correct = 0 for example in test_data: prompt = example["instruction"] expected = example["output"] # Gera resposta response = generate(model, prompt) # Compara (pode ser exact match ou LLM-as-judge) if matches(response, expected): correct += 1 accuracy = correct / len(test_data) print(f"Acurácia no test set: {accuracy:.2%}") return accuracy evaluate_model(model, test_data) # Acurácia no test set: 87.3%
Overfitting em fine-tuning
❌ Overfitting
Sintoma: acurácia no treino = 99%, no teste = 60%
Causa: poucos dados, muitos epochs, modelo muito grande
Modelo decorou o dataset, não generaliza.
✅ Ideal
Sintoma: acurácia no treino = 90%, no teste = 87%
Causa: dados suficientes, epochs adequados
Modelo aprendeu padrões, generaliza bem.
Como evitar overfitting
Mais dados
A solução mais eficaz. Quanto mais exemplos, mais difícil decorar.
Early stopping
Para o treinamento quando a perda de validação começa a subir.
Dropout
Desativa neurônios aleatoriamente. lora_dropout=0.05 ajuda.
Rank menor
r=8 em vez de r=64 reduz capacidade e previne overfitting.
6 O combo RAG + Fine-tuning
O melhor dos dois mundos — quando usar cada um.
🎮 Simulador: RAG vs Fine-tuning vs Ambos
Escolha o cenário e veja qual abordagem funciona melhor
Arquitetura do combo
# Pipeline RAG + Fine-tuning # 1. Modelo base fine-tuned para o domínio base_model = load_model("meta-llama/Llama-3.1-8B") model = PeftModel.from_pretrained(base_model, "./nimbus-adapter") # ↑ Modelo já entende jargão, tom e processos da Nimbus Cloud # 2. Usuário faz pergunta question = "Qual o timeout do endpoint /v2/sync?" # 3. RAG busca chunks relevantes chunks = vector_db.search(question, top_k=5) # ↑ Chunks atualizados dos documentos mais recentes # 4. Monta prompt com contexto prompt = f"""SYSTEM: Você é o Nimbus Assistant. Responda APENAS com base no contexto. Cite fontes. CONTEXTO: {format_context(chunks)} PERGUNTA: {question}""" # 5. Modelo fine-tuned gera resposta response = model.generate(prompt, temperature=0.2) # ↑ Modelo entende o domínio (fine-tuning) E usa docs atualizados (RAG) print(response) # "O timeout padrão do endpoint /v2/sync é 30 segundos [Fonte: Docs API v3.2]."
Quando usar cada componente
| Necessidade | Solução | Exemplo |
|---|---|---|
| Conhecimento atualizado | 🔍 RAG | Documentos de ontem, preços de hoje |
| Tom/estilo específico | 🎯 Fine-tuning | Respostas formais da Nimbus Cloud |
| Jargão técnico | 🎯 Fine-tuning | "NIMBUS_TIMEOUT", "endpoint /v2/sync" |
| Citação de fontes | 🔍 RAG | "[Fonte: Ticket #4521]" |
| Raciocínio complexo | 🎯 Fine-tuning | Classificar tickets com múltiplos critérios |
| Latência muito baixa | 🎯 Fine-tuning | Resposta em <500ms |
| Precisão máxima | 🔗 RAG + Fine-tuning | Modelo especialista + docs atualizados |
7 Custos e infraestrutura
Quanto custa fazer fine-tuning — e onde rodar.
Custos estimados
| Atividade | Modelo | Dataset | Custo (GPU cloud) | Tempo |
|---|---|---|---|---|
| QLoRA | Llama 3 8B | 5.000 exemplos | ~$5-10 | 1-2 horas |
| QLoRA | Llama 3 70B | 5.000 exemplos | ~$30-50 | 3-5 horas |
| LoRA | Llama 3 8B | 5.000 exemplos | ~$20-30 | 2-3 horas |
| Full FT | Llama 3 8B | 5.000 exemplos | ~$200-500 | 8-12 horas |
Onde treinar
GPU local
RTX 3060 (12GB) roda QLoRA 7B. Custo único, sem mensalidade. Ideal para testes.
Cloud GPUs
RunPod, Lambda Labs, Vast.ai. $0.30-0.80/hora por A100. Paga só o que usar.
Plataformas especializadas
Hugging Face AutoTrain, Together AI, Anyscale. Mais caro, mas mais simples.
Enterprise
AWS SageMaker, Azure ML, GCP Vertex. Integração com infraestrutura corporativa.
Inferência — rodando o modelo fine-tuned
# Opção 1: Ollama (mais simples, local) # Converter adapter para formato GGUF python convert_lora_to_gguf.py --adapter ./nimbus-adapter --output ./nimbus.gguf # Rodar com Ollama ollama run ./nimbus.gguf # Opção 2: vLLM (alta performance, produção) from vllm import LLM, SamplingParams llm = LLM( model="meta-llama/Llama-3.1-8B", enable_lora=True, max_lora_rank=16 ) llm.lora_request = LoRARequest("nimbus", 1, "./nimbus-adapter") outputs = llm.generate(prompts, SamplingParams(temperature=0.2)) # Opção 3: API comercial (mais caro, sem infraestrutura) # Fine-tune via OpenAI, Anthropic ou Together AI # Paga por token gerado, sem GPU
Checklist de produção
| Item | Status |
|---|---|
| Dataset curado e balanceado | ✅ Obrigatório |
| Test set separado (10-20%) | ✅ Obrigatório |
| Avaliação com métricas claras | ✅ Obrigatório |
| Monitoramento de drift (modelo degrada com o tempo?) | ✅ Recomendado |
| Versionamento de adapters | ✅ Recomendado |
| Fallback para modelo base | ✅ Recomendado |
| Testes de segurança (prompt injection) | ✅ Obrigatório |
8 Conexão com RAG e próximos passos
Como fine-tuning completa o pipeline RAG — e o que vem depois.
Evolução completa do curso
| Módulo | Conceito | Aplicação no sistema final |
|---|---|---|
| Módulo 0 | Introdução à IA | Entender o que é possível |
| Módulo 1 | ML Clássico | Clustering de documentos, similaridade |
| Módulo 2 | Redes Neurais | Base dos embeddings |
| Módulo 3 | NLP | Tokenização, embeddings de texto |
| Módulo 4 | Transformers | Arquitetura dos LLMs e embeddings |
| Módulo 5 | LLMs | Motor de geração do RAG |
| Módulo 6 | Prompt Engineering | Prompts robustos para RAG |
| Módulo 7 | RAG | Pipeline de busca + geração |
| Módulo 8 | Agents | RAG com raciocínio e autonomia |
| Módulo 9 | Multimodal | RAG com imagens, áudio, vídeo |
| Módulo 10 | Fine-tuning | Modelo especialista do domínio |
| Módulo 11 | MLOps | Colocar tudo em produção |
O sistema final da Nimbus Cloud
# Arquitetura completa # 1. Usuário faz pergunta (texto, áudio ou imagem) input = get_user_input() # 2. Se for áudio, transcreve (Whisper) if is_audio(input): input = whisper.transcribe(input) # 3. Se for imagem, extrai descrição (LLM multimodal) if is_image(input): input = llava.describe(input) # 4. RAG busca chunks relevantes chunks = vector_db.search(input, top_k=5) # 5. Agent decide se precisa buscar mais if agent.needs_more_info(chunks): chunks += agent.search_more(input) # 6. Monta prompt com contexto prompt = build_prompt(chunks, input) # 7. Modelo fine-tuned gera resposta response = fine_tuned_model.generate(prompt) # 8. Opcional: converte resposta em áudio (TTS) if user_wants_audio(): response = piper.tts(response) # 9. Retorna resposta ao usuário send_response(response) # 10. Log tudo para observabilidade langfuse.trace(input, chunks, prompt, response)
O que você construiu ao longo do curso
Base teórica
Entende como IA funciona, de ML clássico a LLMs.
Habilidades práticas
Sabe implementar RAG, fine-tuning, agents.
Visão de produto
Sabe quando usar cada técnica e como combinar.
Produção
Pronto para colocar sistemas de IA no mundo real.
🎯 Quiz — teste seu conhecimento
Clique em uma alternativa para ver se acertou.
→ O que vem a seguir?
Agora que você sabe treinar modelos, vamos aprender a colocá-los em produção de forma robusta.
Conceitos que vamos construir aqui
Observabilidade
Langfuse, Arize — rastreando cada etapa do pipeline.
Versionamento
MLflow, DVC — versionando modelos e datasets.
Drift Detection
Monitorando se o modelo está degradando com o tempo.
CI/CD para IA
Automatizando deploy e re-treinamento.